package com.apes.fn.business.insurance.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.crm.business.model.InsuranceCompanyDetail;
import com.apes.crm.business.repository.InsuranceCompanyDetailRepository;
import com.apes.fn.business.insurance.modle.InsuranceOrder;
import com.apes.fn.business.insurance.modle.PolicyInformation;
import com.apes.fn.business.insurance.modle.PolicyInformationException;
import com.apes.fn.business.insurance.modle.PolicyInformationItem;
import com.apes.fn.business.insurance.repository.PolicyInformationExceptionRepository;
import com.apes.fn.business.insurance.repository.PolicyInformationRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxEventService;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.soe.metadata.BusinessAttributeValue;
import com.apes.framework.plugin.soe.store.database.repository.BusinessAttributeValueRepository;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.pi.model.Timestamp;
import com.apes.pi.repository.TimestampRepository;
import com.apes.pi.service.PiManager;
import com.apes.scm.masterdata.area.model.Area;
import com.apes.scm.masterdata.area.repository.AreaRepository;
import com.apes.scm.masterdata.contrast.model.ContrastPartyCode;
import com.apes.scm.masterdata.contrast.repository.ContrastPartyCodeRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apestech.framework.json.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @ClassName : PolicyInformationService
 * @Description : 业务层
 * @Author : WSJ
 * @Date: 2020-04-28 17:06
 */
@Service("policyInformationService")
public class PolicyInformationService extends DomainService {
    @Autowired
    private PolicyInformationRepository policyInformationRepository;
    @Autowired
    private PiManager piManager;
    @Autowired
    private PolicyInformationExceptionRepository exceptionRepository;
    @Autowired
    private PartyRoleRepository roleRepository;
    @Autowired
    private BusinessAttributeValueRepository attributeValueRepository;

    @Autowired
    private TimestampRepository timestampRepository;

    @Value("${apes.switched:false}")
    private Boolean switched;

    public void getPolicyInformation () throws Exception {
        //得到APP保单数据
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd.HHmmss.SSS");
        //获取北京时间的时间戳
        String dateTime = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
        //首先获取到最新调用接口时间
        Timestamp timestamp = timestampRepository.findOne("fn.insurance.queryInsurance");
        JSONObject response = getAPPData(timestamp,"1");
        if (response.getBoolean("success")) {
            JSONArray data = response.getJSONArray("data");
            JSONArray request = new JSONArray();  //用于把生成的保单信息同步给老框架
            if (data.size() >0) {
                data.forEach(
                        item -> {
                            JSONObject parameters = JSONObject.parseObject(item.toString());
                            try {
                                getPolicyInformation(request, parameters);
                            } catch (RuntimeException e) {
                                //无用
                                insertException(parameters, e);
                                throw new RuntimeException(e);
                            }
                        }
                );
                //如果拉取到数据,则需要以app排序后得最后一条数据得时间戳为准
                Date date = changeTime(data.getJSONObject(data.size() - 1).getJSONObject("order").getLongValue("finishOrderAt"));
                Instant instant = date.toInstant();
                LocalDateTime localDateTime = instant.atZone(ZoneOffset.of("+8")).toLocalDateTime();
                dateTime = localDateTime.format(formatter);
            }else {
                //获取北京时间的时间戳
                dateTime = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
            }
//            if (request.size() > 0&&!switched) {
//                try {
//                    //同步旧系统
//                    JSONObject resultJson = piManager.synErp(
//                            "ipmBusinessAffairsService.insertYXBDXX", MapUtil.mapper(
//                                    "dataArray",request
//                            )  );
//                } catch (Exception e) {
//                    throw new RuntimeException("同步旧框架报错," + e);
//                }
//            }
            insertTimestamp(timestamp,"fn.insurance.queryInsurance",dateTime);
        }
    }

    /**
     * 生成保单信息
     * @param request
     * @param parameters
     */
    private void getPolicyInformation(JSONArray request, JSONObject parameters) throws RuntimeException{
        checkParameter(parameters);
        //如果supplyCompanyCode 不为空,则直接取该字段
        parameters.put("supplier", StringUtils.isEmpty(parameters.getString("supplyCompanyCode"))? getInsuranceCompany(parameters).getSupplier().getId():parameters.getString("supplyCompanyCode"));
        parameters .put("policyNumber",parameters.getString("carLicense"));
        //订单信息
        JSONObject order = parameters.getJSONObject("order");
        JSONObject  commerceCommissionMsg = new JSONObject();
        JSONObject  forceCommissionMsg = new JSONObject();
        //商业险佣金信息
        if (parameters.containsKey("commerceCommissionMsg")) {
            commerceCommissionMsg = parameters.getJSONObject("commerceCommissionMsg");
        };
        //交强险佣金信息
        if (parameters.containsKey("forceCommissionMsg")) {
            forceCommissionMsg = parameters.getJSONObject("forceCommissionMsg"); //交强险佣金信息
        }
        //把order里的公共参数取出来塞到parameters
        try {
            parameters.put("receiptDate", changeTime(order.getLong("finishPaymentAt")));
            parameters.put("issueDate", changeTime(order.getLong("finishOrderAt")));
            parameters.put("createdAt", changeTime(parameters.getLong("createdAt")));
        } catch (Exception e) {
            throw new RuntimeException("订单的出单时间或支付时间不能为空!!!");
        }
        //生成保单信息,必须存在交强险或者商业险
        if (StringUtils.isEmpty(order.getString("forceFormOrderNo")) && StringUtils.isEmpty(order.getString("commerceFormOrderNo"))) {
            throw new RuntimeException("生成保单信息,必须存在交强险或者商业险!!!");
        }
        /* 1.可能一个单存在交强险 和商业险 险种类别(0:商业险；1：交强险),同时存在时则需要分别生成保单;
           2.可能存在
         */
        if (!StringUtils.isEmpty(order.getString("forceFormOrderNo"))) {
            if (Objects.isNull(forceCommissionMsg)) throw new RuntimeException("存在交强险保单号,交强险佣金信息不能为空!!!");
            try {
                parameters.put("insuranceType","1");
                parameters.put("insuranceAmount",parameters.getDouble("itemForcePrice"));//保费
                parameters.put("netPremium",parameters.getDouble("pureForceAmount"));//净保费

                parameters.put("startDate", parameters.getDate("forceStartDate"));
                parameters.put("endDate", parameters.getDate("forceEndDate"));
                // JSONObject ratio = getCommissionRatio(parameters);
                parameters.put("policyNumber",order.getString("forceFormOrderNo"));
                PolicyInformation information = policyInformationRepository.findOne(parameters.getString("policyNumber"));
                if (Objects.isNull(information)){
                    request.add(insertPolicyInformation(parameters, forceCommissionMsg));
                }
            } catch (RuntimeException e) {
                throw new RuntimeException ("交强险信息报错:"+e);
            }
        }

        if (!StringUtils.isEmpty(order.getString("commerceFormOrderNo"))) {
            if (Objects.isNull(commerceCommissionMsg)) throw new RuntimeException("存在商业险保单号,商业险佣金信息不能为空!!!");
            try {
                parameters.put("insuranceType","0");
                parameters.put("insuranceAmount",parameters.getDouble("commerceTotalDiscounted"));//保费
                parameters.put("netPremium",parameters.getDouble("pureCommerceAmount"));//净保费
                parameters.put("startDate", parameters.getDate("commerceStartDate"));
                parameters.put("endDate", parameters.getDate("commerceEndDate"));
                parameters.put("policyNumber",order.getString("commerceFormOrderNo"));
                PolicyInformation information = policyInformationRepository.findOne(parameters.getString("policyNumber"));
                if (Objects.isNull(information))
                request.add(insertPolicyInformation(parameters, commerceCommissionMsg));
            } catch (RuntimeException e) {
                throw new RuntimeException("商业险信息报错:" + e);
            }
        }
    }

    /**
     * 记录接口报错信息
     * @param parameters
     * @param e
     */
    private void insertException(JSONObject parameters, RuntimeException e) {
        //报错,则把保单号或者对应的 车牌记录到错误信息表
        PolicyInformationException exception = new PolicyInformationException();
        if (parameters.containsKey("policyNumber")) {
            exception.setId(parameters.getString("policyNumber"));
        }else {
            exception.setId(parameters.getString("carLicense"));
        }
        exception.setError(e.toString());
        exceptionRepository.saveAndFlush(exception);
    }

    /**
     * 记录接口时间戳
     *
     * @param timestamp
     */
    public void insertTimestamp(Timestamp timestamp,String APIName,String dataString) {
        //记录接口调用成功时间戳
        if (timestamp == null) {
            timestamp = new Timestamp();
        }
        timestamp.setId(APIName);
        timestamp.setTime(dataString);
        timestamp.setValid(true);
        timestamp.setType("timestamp");
        timestampRepository.saveAndFlush(timestamp);
    }

    public JSONObject getAPPData(Timestamp timestamp,String type) throws ParseException {
        Map<String, Object> body = new HashMap<>();
        ZoneOffset offset = ZoneOffset.of("+8");
        body.put("type", type);
        if (timestamp != null ) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd.HHmmss.SSS");
            Date dateTime = dateFormat.parse(timestamp.getTime());
            body.put("timestamp",
                    dateTime.toInstant().atOffset(offset).toLocalDateTime().toEpochSecond(offset));
        }else {
            body.put("timestamp", LocalDateTime.now().toEpochSecond(offset));
        }
        // body.put("fields","id,carLicense,company,companyLabel,createdAt,order.forceFormOrderNo,cityCode,cityNameLabel,provinceNameLabel,forceStartDate,forceEndDate," +
        //         "commerceStartDate,commerceEndDate,isHaveForce,isHaveCommerce,vin,engineCode,vehicleBrand,newBuyPrice,taxMoney,debutDate,belongType,belongTypeLabel," +
        //         "storeCode,storeLabel,staffName,staffCode,itemThirdPrice,businessType,businessTypeLabel,pureCommerceAmount,commerceTaxAmount,commerceTotalDiscounted," +
        //         "carUseType,carUseTypeLabel,vendorCompanyLabel,itemForcePrice,order.commerceFormOrderNo,order.finishPaymentAt,order.finishOrderAt,policyTitle,policyType," +
        //         "policyTypeLabel,policyReturnType,policyReturnTypeLabel,formList,order.status,order.statusLabel,commissionPercent,commissionMsg,order.refundAt,order.dischargeInsuranceAt," +
        //         "forceCommissionAmount,commerceCommissionAmount,performanceCommissionAmount");
        body.put("fields","*,order.*,formList.*,forceCommissionMsg.*,commerceCommissionMsg.*,performanceCommissionMsg.*,insuranceRefund.refundActualInsuranceTotalPrice");
        JSONObject query = new JSONObject();
        query.put("perPage",50);
        query.put("page",1);
        query.put("sort","id");
        body.put("query", query);
        Map param = MapUtil.mapper(
                "body", body,
                "headers", MapUtil.mapper(
                        "method", "v1/insurance/index",
                        "action", "get"
                )
        );
        return JSONObject.parseObject(this.invoke("pi.app.ext", param));
    }

    /**
     * 获取佣金比率
     * @param param
     */
    private JSONObject getCommissionRatio (JSONObject param) throws RuntimeException {
        //先获取该公司对应的佣金比率  调用老框架
        JSONObject request = new JSONObject();
        //把新框架编码转换为老框架编码
        ContrastPartyCode partyCode = getOldSystemCode(param);
        Dept dept = SpringManager.getBean(DeptRepository.class).findOne(param.getString("storeCode"));
        request.put("GYSID", partyCode.getGysid());
        request.put("XZLB", param.getString("insuranceType"));
        request.put("DJGCID", "BX01");
        request.put("MDID", dept.getOrigin());
        request.put("XJJB", 0);
        JSONObject resultObj = piManager.synErp("ipmBusinessAffairsService.getRate", request);
        if (!resultObj.getBoolean("success")) {
            throw new RuntimeException(resultObj.getString("msg"));
        }else {
            JSONObject result = JSONObject.parseObject(resultObj.get("obj").toString());
            if (result.getFloatValue("Y001") <= 0 || result.getFloatValue("Y002") <= 0)
                throw new RuntimeException("未定义佣金比率！！！");
            return result;
        }
    }
    /**
     * 新增保单信息
     * @param policyInfo 保单信息
     */
    private Map insertPolicyInformation (JSONObject param, JSONObject policyInfo)  {
        checkExists(param);
        PolicyInformation policyInformation = null;
        try {
            policyInformation = packagePolicyInformation(param);
        } catch (Exception e) {
            throw new RuntimeException("保单主体信息报错:" + e);
        }
        PolicyInformationItem informationItem = null;
        policyInformation = getPolicyInformationData(policyInfo, policyInformation);
        pushMessageForCalculateFee(policyInformation);
        //封装老系统对应的供应商编码以及门店编码
        return  packageOldInformation(policyInformation);
    }

    /**
     * 将保单信息明细补充整
     * @param policyInfo
     * @param policyInformation
     * @return
     */
    private PolicyInformation getPolicyInformationData(JSONObject policyInfo, PolicyInformation policyInformation) {
        String commissionType = "PolicyInformationItem.commissionType.A"; //默认为正常佣金
        try {
            PolicyInformationItem informationItem = packagePolicyInformationItem(commissionType, policyInfo);
            informationItem.setPolicyInformation(policyInformation);
            policyInformation.getPolicyInformationItems().add(informationItem);
        } catch (Exception e) {
            throw new RuntimeException("保单正常佣金信息报错:" + e);
        }
        if (policyInfo.getDoubleValue("insuranceAllowanceAmount") > 0 || policyInfo.getDoubleValue("commissionAllowanceAmount") > 0) {
            commissionType = "PolicyInformationItem.commissionType.B"; //追加佣金
            PolicyInformationItem informationItem = packagePolicyInformationItem(commissionType, policyInfo);
            informationItem.setPolicyInformation(policyInformation);
            policyInformation.getPolicyInformationItems().add(informationItem);
        }
        policyInformation = policyInformationRepository.saveAndFlush(policyInformation);
        return policyInformation;
    }

    /**
     * 检查是否存在该保单号的保单信息
     * @param param
     */
    private void checkExists (JSONObject param) {
        PolicyInformation policyInformation = policyInformationRepository.findOne(param.getString("policyNumber"));
        if (policyInformation != null) throw new RuntimeException("该保单号已经存在,请检查保单号是否重复!!! 保单号: " +param.getString("policyNumber"));
    }
    /**
     * 获取保险公司对应的供应商
     * @param param
     */
    public InsuranceCompanyDetail getInsuranceCompany (JSONObject param) {
        Assert.isTrue(!StringUtils.isEmpty(param.getString("company")), "保险公司不能为空!!!");

        //找到对应的省市
        Dept dept = SpringManager.getBean(DeptRepository.class).findOne(param.getString("storeCode"));
        if (dept == null) throw new RuntimeException("该门店编码在系统中无对应信息,编码: " + param.getString("storeCode"));
        //门店信息(省市)
        Area province = dept.getCompany().getParty().getCorporate().getRegProvince();
        Area city = dept.getCompany().getParty().getCorporate().getRegCity();
        List<InsuranceCompanyDetail> list = SpringManager.getBean(InsuranceCompanyDetailRepository.class).findAll(
                JpaDsl.toCriteriaByEq("province",province,"city",city,"APPCode",param.getString("company"))
        );
        //根据门店的省市 和app 编码查询对应的公司,如果没有,责默认为广东省广州市
        if (list.size() == 0){
            province = SpringManager.getBean(AreaRepository.class).findOne("440000");
            city = SpringManager.getBean(AreaRepository.class).findOne("440100");
            list = SpringManager.getBean(InsuranceCompanyDetailRepository.class).findAll(
                    JpaDsl.toCriteriaByEq("province",province,"city",city,"APPCode",param.getString("company"))
            );
            if (list.size() == 0){
                throw new RuntimeException("该APP编码无对应公司, APP编码: " +param.getString("company"));
            }
        }
        return list.stream().findFirst().orElse(null);
    }
    /**
     * 封装保单信息
     * @param param
     */
    private PolicyInformation  packagePolicyInformation(JSONObject param)  {
        JSONObject performanceCommissionMsg = param.getJSONObject("performanceCommissionMsg"); // 提成信息
        if(Objects.isNull(performanceCommissionMsg)) throw new RuntimeException("保单提成信息为空!!!");
        PolicyInformation information = new PolicyInformation();
        //时间相关
        information.setStartDate(param.getDate("startDate"));
        information.setEndDate(param.getDate("endDate"));
        information.setIssueDate(param.getDate("issueDate"));
        information.setReceiptDate(param.getDate("receiptDate"));
        information.setQuoteDate(param.getDate("createdAt"));

        //车辆相关
        information.setPlateLicense(param.getString("carLicense"));
        information.setVin(param.getString("vin"));
        information.setEngineModel(param.getString("engineCode"));
        information.setCarPrice(param.getDouble("newBuyPrice"));
        information.setCarOwnership(param.getString("carOwnership"));
        information.setUse(param.getString("carUseType"));

        //提成相关
        information.setAPPOrder(param.getString("id"));
        information.setDiscountType(performanceCommissionMsg.getString("discountType"));
        information.setDiscountTypeName(performanceCommissionMsg.getString("discountTypeLabel"));
        information.setFnProfit(performanceCommissionMsg.getDoubleValue("normalAmount"));
        information.setFnProfitRatio(performanceCommissionMsg.getDoubleValue("normalPercent")/100);
        information.setTotalPercent(performanceCommissionMsg.getDoubleValue("totalPercent")/100);
        information.setCommissionTotalAmount(performanceCommissionMsg.getDoubleValue("totalAmount"));
        information.setAllowanceAmount(performanceCommissionMsg.getDoubleValue("allowanceAmount"));
        information.setAllowancePercent(performanceCommissionMsg.getDoubleValue("allowancePercent")/100);


        //保险相关
        information.setId(param.getString("policyNumber"));
        information.setType(param.getString("businessType"));
        information.setInsuranceType(param.getString("insuranceType"));
        information.setCarShipTax(param.getDouble("taxMoney"));
        information.setCity(param.getString("cityNameLabel"));
        information.setProvince(param.getString("provinceNameLabel"));
        information.setItemThirdPrice(param.getDouble("itemThirdAmount"));
        information.setInsuranceAmount(param.getDoubleValue("insuranceAmount"));
        information.setNetPremium(param.getDoubleValue("netPremium"));
        information.setSourceBusinessType(PolicyInformation.CONST_SOURCE_FORM_APP);
        if (information.getNetPremium() <= 0) throw new RuntimeException("净保费不能为零!!!");

        //封装保单信息中的其他实体
        packageEntity(param, information);

        return  information;
    }

    /**
     * 包装保单信息的实体
     * @param param
     * @param information
     */
    private void packageEntity(JSONObject param, PolicyInformation information) {
        //获取门店, 供应商 , 业务员
        Dept dept = SpringManager.getBean(DeptRepository.class).findOne(param.getString("storeCode"));
        if (dept == null) throw new RuntimeException("该门店编码在系统中无对应信息,编码: " + param.getString("storeCode"));
        information.setDept(dept);
        information.setCompany(dept.getCompany());
        PartyRole supplier = roleRepository.findOne(param.getString("supplier"));
        if (supplier == null) throw new RuntimeException("该供应商在系统中无对应信息,编码: " + param.getString("supplier"));
        information.setSupplier(supplier);
        PartyRole staff = roleRepository.findOne(param.getString("staffCode"));
        if (staff == null) throw new RuntimeException("该员工在系统中无对应信息,编码: " + param.getString("staffCode"));
        information.setSalesman(staff);
    }

    //转换时间戳格式时间为系统时间
    public Date changeTime(Long time) throws ParseException {
        if(time >0){
            long dates = time*1000;
            Date date = new Date();
            date.setTime(dates);
            return date;
        }else {
            return null ;
        }
    }


    /**
     * 封装保单佣金信息
     * @param policyInfo 佣金信息
     */
    private PolicyInformationItem  packagePolicyInformationItem(String commissionType,JSONObject policyInfo) {
        PolicyInformationItem informationItem = new PolicyInformationItem();
        //正常佣金
        if (Objects.equals("PolicyInformationItem.commissionType.A",commissionType)) {
            informationItem.setCommission(policyInfo.getDoubleValue("insuranceAmount"));
            informationItem.setCommissionRatio(policyInfo.getDoubleValue("insurancePercent")/100);
            informationItem.setFnCommission(policyInfo.getDoubleValue("commissionNormalAmount"));
            informationItem.setFnCommissionRatio(policyInfo.getDoubleValue("commissionNormalPercent")/100);
        } else {
            informationItem.setCommission(policyInfo.getDoubleValue("insuranceAllowanceAmount"));
            informationItem.setCommissionRatio(policyInfo.getDoubleValue("insuranceAllowancePercent")/100);
            informationItem.setFnCommission(policyInfo.getDoubleValue("commissionAllowanceAmount"));
            informationItem.setFnCommissionRatio(policyInfo.getDoubleValue("commissionAllowancePercent")/100);
        }
        informationItem.setCommissionType( attributeValueRepository.findOne(commissionType));
        return  informationItem;
    }

    /**
     * 检查传入参数是否有必需参数为空
     * @param param
     */
    private void  checkParameter(JSONObject param) {
        for (Map.Entry<String, Object> stringObjectEntry : param.entrySet()) {
            Map.Entry<String, String> entry = (Map.Entry) stringObjectEntry;
            if ("storeCode".equals(entry.getKey()) || "company".equals(entry.getKey())
                    || "staffCode".equals(entry.getKey()) || "carLicense".equals(entry.getKey())
                    || "id".equals(entry.getKey())) {
                if (StringUtils.isEmpty(entry.getValue())) throw new RuntimeException("生成保单信息的必需参数不能为空!!!");
            }
        }
        //检查对应门店编码,是否在系统中存在
        Dept dept = SpringManager.getBean(DeptRepository.class).findOne(param.getString("storeCode"));
        if (dept == null) throw new RuntimeException("系统中未存在该门店, 编码: " + param.getString("storeCode"));
    }

    /**
     * 获取老框架编码
     * @param param
     */
    private ContrastPartyCode getOldSystemCode(JSONObject param) {
        PartyRole supplier = roleRepository.findOne(param.getString("supplier"));
        ContrastPartyCode partyCode =
                SpringManager.getBean(ContrastPartyCodeRepository.class).findFirstByParty(supplier.getParty());
        if (partyCode == null ) throw new RuntimeException("该供应商编码无对应的当事人角色!!!");
        return  partyCode;
    }


    /**
     * 手动同步保单信息到老框架
     *
     */
    public void synPolicyInformation(SimpleRequest request) {
        String id = request.get("id");
        PolicyInformation policyInformation = policyInformationRepository.findOne(id);
        JSONArray dataArray = new JSONArray();
        Map map = packageOldInformation(policyInformation);
        dataArray.add(map);
//        try {
//            //同步旧系统
//            JSONObject resultJson = piManager.synErp(
//                    "ipmBusinessAffairsService.insertYXBDXX", MapUtil.mapper(
//                            "dataArray",dataArray
//                    )  );
//        } catch (Exception e) {
//            throw new RuntimeException("同步旧框架报错," + e);
//        }
    }

    private Map packageOldInformation(PolicyInformation policyInformation) {
        Map<String, Object> map = MapUtil.mapped(policyInformation);
        Dept dept = policyInformation.getDept();
        assert map != null;
        PartyRole supplier = policyInformation.getSupplier();
        ContrastPartyCode partyCode =
                SpringManager.getBean(ContrastPartyCodeRepository.class).findFirstByParty(supplier.getParty());

        map.put("dept", MapUtil.mapper("id",dept.getOrigin(),"name",dept.getName()));
        map.put("supplier", MapUtil.mapper("id", partyCode.getGysid(), "name", supplier.getName()));
        return  map;
    }

    /***
     * 推送计算平台服务费消息
     */

    public void pushMessageForCalculateFee(PolicyInformation policyInformation) {
        Map msg = MapUtil.mapper(
                "id", policyInformation.getId()
        );

        OutboxPayloadWrapper wrapper = new OutboxPayloadWrapper();
        wrapper.setSubscriber("fn.partnerCheck.calculatePolicyInformationFee");
        wrapper.setAggregateId(policyInformation.getId());
        try {
            wrapper.setPayload(JSON.toJSONString(msg));
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        SpringManager.getBean(OutboxEventService.class).sendSaveEvent(wrapper);

    }

    /**
     * 获取 保单信息负单信息
     * @throws Exception
     */
    public void saveMinusPolicyInformation () throws Exception {
        //得到APP保单数据
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd.HHmmss.SSS");
        String dateTime;
        //首先获取到最新调用接口时间
        Timestamp timestamp = timestampRepository.findOne("fn.insurance.queryMinusInsurance");
        JSONObject response = getAPPData(timestamp,"3");
        if (response.getBoolean("success")) {
            JSONArray data = response.getJSONArray("data");
            JSONArray request = new JSONArray();  //用于把生成的保单信息同步给老框架
            if (data.size() >0) {
                data.forEach(
                        item -> {
                            JSONObject parameters = JSONObject.parseObject(item.toString());
                            try {
                                insertMinusPolicyInformation(request, parameters);
                            } catch (RuntimeException e) {
                                throw new RuntimeException(e);
                            }
                        }
                );
                //如果拉取到数据,则需要以app排序后得最后一条数据得时间戳为准
                Date date = data.getJSONObject(data.size() - 1).getJSONObject("order").getDate("finishOrderAt");
                Instant instant = date.toInstant();
                LocalDateTime localDateTime = instant.atZone(ZoneOffset.of("+8")).toLocalDateTime();
                dateTime = localDateTime.format(formatter);
            }else {
                //获取北京时间的时间戳
                dateTime = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
            }
//            if (request.size() > 0) {
//                try {
//                    //同步旧系统
//                    JSONObject resultJson = piManager.synErp(
//                            "ipmBusinessAffairsService.insertYXBDXX", MapUtil.mapper(
//                                    "dataArray",request
//                            )  );
//                } catch (Exception e) {
//                    throw new RuntimeException("同步旧框架报错," + e);
//                }
//            }
            insertTimestamp(timestamp,"fn.insurance.queryMinusInsurance",dateTime);
        }
    }


    /**
     *
     * @param result 需要返回得结果集
     * @param param 订单信息
     */
    public void insertMinusPolicyInformation (JSONArray result,JSONObject param) throws RuntimeException {
        JSONObject order = param.getJSONObject("order");
        // status 状态值，4-待出单，7-已退款，6-生成保单，8-已退保 9-已作废
        String status = order.getString("status");
        if (!Objects.equals("9",status)) {
            return;
        }
        String id = param.getString("id");
        //查询该app订单号是否在系统生成了 正向得有效保单信息
        List<PolicyInformation> informationList = policyInformationRepository.findAll(JpaDsl.toCriteriaByEq("APPOrder", id));
        for (PolicyInformation policyInformation : informationList) {
            PolicyInformation newPolicyInformation = new PolicyInformation();
            ReflectUtil.copyAll(policyInformation,newPolicyInformation,"id","createDate");
            newPolicyInformation.setId("-"+policyInformation.getId());
            newPolicyInformation.setCommissionTotalAmount(-1 * newPolicyInformation.getCommissionTotalAmount());
            newPolicyInformation.setAllowanceAmount(-1 * newPolicyInformation.getAllowanceAmount());
            newPolicyInformation.setCommissionTotalAmount(-1 * newPolicyInformation.getCommissionTotalAmount());
            for (PolicyInformationItem item : newPolicyInformation.getPolicyInformationItems()) {
                item.setPolicyInformation(newPolicyInformation);
                item.setCommission(-1 * item.getCommission());
                item.setFnCommission(-1 * item.getFnCommission());
            }
            newPolicyInformation = policyInformationRepository.saveAndFlush(newPolicyInformation);
            result.add(packageOldInformation(newPolicyInformation));
        }

    }

    /**
     * app 同步驾意险保单信息
     * @param param
     */
    public  void appSynchronizePolicy (JSONObject param, InsuranceOrder order) {
        JSONArray policyList = param.getJSONArray("policyInformation");
        JSONArray requestArray =new JSONArray();
        for (int i = 0,len = policyList.size(); i < len; i++) {
            JSONObject policy = policyList.getJSONObject(i);
            PolicyInformation information = policyInformationRepository.findOne(policy.getString("id"));
            if(Objects.nonNull(information)) {
                continue;
            }else {
                information = new PolicyInformation();
            }
            information.setId(policy.getString("id"));
            information.setFnProfit(policy.getDoubleValue("fnProfit"));
            information.setFnProfitRatio(policy.getDoubleValue("fnProfitRatio"));
            information.setAllowanceAmount(policy.getDoubleValue("allowanceAmount"));
            information.setAllowancePercent(policy.getDoubleValue("allowancePercent"));
            information.setTotalPercent(policy.getDoubleValue("totalPercent"));
            information.setCommissionTotalAmount(policy.getDoubleValue("commissionTotalAmount"));
            information.setInsuranceAmount(policy.getDoubleValue("insuranceAmount"));
            information.setSourceBusinessType(PolicyInformation.CONST_SOURCE_FORM_APP);

            //车辆相关
            information.setVin(param.getString("vin"));
            information.setCity(param.getString("city"));
            information.setProvince(param.getString("province"));
            information.setEngineModel(param.getString("engineModel"));
            information.setCarOwnership(param.getString("carOwnership"));
            information.setStartDate(param.getDate("startDate"));
            information.setEndDate(param.getDate("endDate"));
            information.setIssueDate(param.getDate("issueDate"));
            information.setNetPremium(param.getDoubleValue("netPremium"));

            information.setPlateLicense(order.getLicensePlate());
            information.setInsuranceType("2");
            information.setDept(order.getDept());
            information.setCompany(order.getCompany());
            information.setSalesman(order.getSalesman());
            information.setSupplier(order.getSupplier());
            information.setAPPOrder(order.getAPPOrder());
            information.setReceiptDate(order.getReceiptDate());
            JSONArray items = policy.getJSONArray("policyInformationItem");
            if (items.size() == 0 ) {
                throw new RuntimeException("保单信息佣金明细不能为空!!!");
            }
            for (int j = 0,size = items.size(); j < size; j++) {
                JSONObject item = items.getJSONObject(j);
                PolicyInformationItem informationItem = new PolicyInformationItem();
                informationItem.setPolicyInformation(information);
                informationItem.setCommission(item.getDoubleValue("commission"));
                informationItem.setCommissionRatio(item.getDoubleValue("commissionRatio"));
                informationItem.setFnCommission(item.getDoubleValue("fnCommission"));
                informationItem.setFnCommissionRatio(item.getDoubleValue("fnCommissionRatio"));
                String commissionType = item.getString("commissionType");
                BusinessAttributeValue attributeValues = attributeValueRepository.findAll(
                        JpaDsl.toCriteriaByEq("businessAttribute.id", "PolicyInformationItem.commissionType", "code", commissionType)
                ).stream().findFirst().orElseThrow(() -> new RuntimeException("系统中未找到对应的佣金类型!!!"));
                informationItem.setCommissionType(attributeValues);
                information.getPolicyInformationItems().add(informationItem);
            }
            information = policyInformationRepository.saveAndFlush(information);
            requestArray.add(packageOldInformation(information));
        }

//        if (requestArray.size() > 0) {
//            try {
//                //同步旧系统
//                JSONObject resultJson = piManager.synErp(
//                        "ipmBusinessAffairsService.insertYXBDXX", MapUtil.mapper(
//                                "dataArray",requestArray
//                        )  );
//            } catch (Exception e) {
//                throw new RuntimeException("同步旧框架报错," + e);
//            }
//        }
    }

    /**
     * app 新增有效保单信息
     * @param request
     * @return
     */
    public  String  insertPolicyInformation (SimpleRequest request) {
        PolicyInformation information = request.getO(PolicyInformation.class);
        JSONObject param = request.getJO();
        PolicyInformation policyNumber = policyInformationRepository.findOne(param.getString("policyNumber"));
        if (policyNumber!=null) throw new RuntimeException("保单号已存在无法同步");
        information.setId(param.getString("policyNumber"));
        information.setCompany(information.getDept().getCompany());
        information.setSourceBusinessType(PolicyInformation.CONST_SOURCE_FORM_APP);
        policyInformationRepository.saveAndFlush(information);
        JSONArray array = new JSONArray();
        array.add(packageOldInformation(information));
//        if (array.size() > 0) {
//            try {
//                //同步旧系统
//                JSONObject resultJson = piManager.synErp(
//                        "ipmBusinessAffairsService.insertYXBDXX", MapUtil.mapper(
//                                "dataArray",array
//                        )  );
//            } catch (Exception e) {
//                throw new RuntimeException("同步旧框架报错," + e);
//            }
//        }
        return information.getId();
    }
}
